package com.dreamchaser.familydevice.shiro;

import com.alibaba.druid.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.Iterator;

/**
 * url=api/resource==GET
 * <p>
 * 重写PathMatchingFilterChainResolver的getChain方法，增加对上述规则的url的支持。
 */
@Slf4j
public class RestPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {
    public RestPathMatchingFilterChainResolver() {
        super();
    }

    public RestPathMatchingFilterChainResolver(FilterConfig filterConfig) {
        super(filterConfig);
    }

    /**
     * 重写filterChain匹配
     *
     * @param request
     * @param response
     * @param originalChain
     * @return javax.servlet.FilterChain
     */
    @Override
    public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
        FilterChainManager filterChainManager = this.getFilterChainManager();
        if (!filterChainManager.hasChains()) {
            return null;
        }
        String requestURI = this.getPathWithinApplication(request);
        if (requestURI.endsWith("/")) {
            requestURI = requestURI.substring(0, requestURI.length() - 1);
        }
        Iterator<String> var6 = filterChainManager.getChainNames().iterator();

        String pathPattern = null;
        String[] strings;

        String chainName = null;

        // 判断url是否匹配，判断是不是有权限

        for (; var6.hasNext();
        ) {
            pathPattern = var6.next();
            strings = pathPattern.split("==");
            if (
                // 判断格式是否匹配
                    (strings.length == 2
                            // 先判断http方法是否一致
                            && StringUtils.equalsIgnoreCase(WebUtils.toHttp(request).getMethod(), strings[1])
                            // 判断url是否match
                            && this.pathMatches(strings[0], requestURI))
                            ||
                            (strings.length == 1 && this.pathMatches(strings[0], requestURI))
            ) {
                // 都匹配 记录
                chainName = pathPattern;
                break;
            }
        }
        // 全部都没有匹配
        if (null == chainName) {

            log.info("not matched chain for requestURI : " + requestURI);
            //return null;
            throw new org.apache.shiro.authc.AuthenticationException("not permission  【requestURI】: " + requestURI+"\n  【Method】："+WebUtils.toHttp(request).getMethod());
        }

        if (log.isTraceEnabled()) {
            log.trace("Matched path pattern [" + chainName + "] for requestURI [" + requestURI + "].  Utilizing corresponding filter chain...");
        }

        return filterChainManager.proxy(originalChain, chainName);
    }
}
